package template_wrapper

import (
	app_global "app/app_src/framework/app/global"
	file_util "app/app_src/framework/util/file"
	"os"
	"sync"
)

type TemplateLoader struct {
	// 路径前缀
	PathPrefix string
	// 路径后缀
	PathSuffix string
	// 是否使用嵌入式文件系统
	UseEmbedFS bool
	// 是否启用缓存
	CacheEnabled bool

	// 模板解析器
	_TemplateParser *TemplateParser

	OnReadFile OnReadFileFunc
}

type OnReadFileFunc func(loader *TemplateLoader, name string) string

// 缓存
var _TemplateCache sync.Map

func NewTemplateLoader(pathPrefix string, pathSuffix string, templateParser *TemplateParser) *TemplateLoader {
	var newLoader TemplateLoader

	newLoader.PathPrefix = pathPrefix
	newLoader.PathSuffix = pathSuffix
	newLoader._TemplateParser = templateParser
	newLoader.UseEmbedFS = false
	newLoader.CacheEnabled = false
	newLoader.OnReadFile = nil

	return &newLoader
}

func NewTemplateLoaderFromConfig(config *TemplateConfig, templateParser *TemplateParser) *TemplateLoader {
	var newLoader TemplateLoader

	newLoader.PathPrefix = config.PathPrefix
	newLoader.PathSuffix = config.PathSuffix
	newLoader._TemplateParser = templateParser
	newLoader.UseEmbedFS = config.UseEmbedFS
	newLoader.CacheEnabled = config.CacheEnabled
	newLoader.OnReadFile = nil

	return &newLoader
}

// 加载模板
func (t *TemplateLoader) LoadTemplate(name string) TemplateWrapper {
	var tmpl TemplateWrapper
	cacheKey := t.PathPrefix + name + t.PathSuffix

	if t.CacheEnabled {
		// 从缓存中获取
		value, ok := _TemplateCache.Load(cacheKey)

		if ok {
			tmpl = value.(TemplateWrapper)
		}
	}

	if tmpl == nil {
		var content string

		// 读取文件
		if t.OnReadFile != nil {
			content = t.OnReadFile(t, name)
		} else {
			content = t.ReadFile(name)
		}

		// 解析模板
		tmpl = t._TemplateParser.ParseTemplate(name, content)

		if t.CacheEnabled {
			// 缓存解析后的模板
			_TemplateCache.Store(cacheKey, tmpl)
		}
	}

	return tmpl
}

// 读取文件
func (t *TemplateLoader) ReadFile(name string) string {
	var content []byte
	var err error

	// 计算模板的路径
	path := t.PathPrefix + name + t.PathSuffix

	if t.UseEmbedFS {
		embedFS := app_global.EmbedFS()
		// 从嵌入式文件系统中获取模板文件并解析
		content, err = embedFS.ReadFile(path)

		if err != nil {
			panic(err)
		}
	} else {
		appDir := app_global.AppDir()
		adjustedPath := file_util.JoinPath(appDir, path)
		// 从本地文件系统中获取模板文件并解析
		content, err = os.ReadFile(adjustedPath)

		if err != nil {
			panic(err)
		}
	}

	return string(content)
}
